
package analiseSintatica.Regras.Expressoes;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSemantica.Tipos.TiposSemanticos;
import java.util.LinkedList;

import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;

/**
 * Contem as regras para a analise sintatica
 * @author nathy
 */
public class RegraElemento extends Regra {


    protected static Regra instancia;
    protected static String estrutura =" <elemento> :=  <primario> | '('<expressao>')'";


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraElemento() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraElemento getInstance() {
        if (instancia == null) {
            instancia = new RegraElemento();
        }
        return (RegraElemento) instancia;
    }
    /**
     * Realiza analise sintatica
     * @param listaTokens - Tokens do codigo
     * @return - Arvore sintatica
     * @throws Exception
     */
@Override
	public TiposSemanticos analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException{
		
        TiposSemanticos tipos = null;
        
		if (listaContem(RegraPrimario.getInstance().getPrimeiro(), listaTokens.getFirst())) {

            	tipos = RegraPrimario.getInstance().analisar(listaTokens);
            
        }else if(listaTokens.getFirst().getLexema().equals("(")){

        		reconheceLexema(listaTokens, "delimitador", "(", estrutura);
        		tipos = RegraExpressao.getInstance().analisar(listaTokens);
        		reconheceLexema(listaTokens, "delimitador", ")", estrutura);

            
        }else{
            ErroSintaticoException e = new ErroSintaticoException();
            e.addErros("Elemento esperado antes do token " + listaTokens.getFirst().getLexema(), estrutura, listaTokens.getFirst().getLinha());
            throw e;
        }
		
        return tipos;
	}



    @Override
    protected void setPrimeiro() {
       this.primeiro = RegraPrimario.getInstance().getPrimeiro();
       this.primeiro.add("(");
    }
}
